package com.alex.seo.service.site;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.hibernate.exception.ConstraintViolationException;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.transaction.annotation.Transactional;

import com.alex.seo.dao.group.SiteGroupDao;
import com.alex.seo.dao.site.SiteDao;
import com.alex.seo.domain.group.SiteGroup;
import com.alex.seo.domain.site.Site;
import com.alex.seo.service.exception.ObjectExistsException;
import com.alex.seo.service.logging.LogType;
import com.alex.seo.service.logging.LoggingService;
import com.alex.seo.service.site.dto.SiteDTO;

@Transactional(rollbackFor = ObjectExistsException.class)
public class SiteServiceBean implements SiteService {

	private LoggingService loggingService;
	
	private SiteDao siteDao;

	private SiteGroupDao siteGroupDao;
	
	@Required
	public void setLoggingService(LoggingService loggingService) {
		this.loggingService = loggingService;
	}
	
	@Required
	public void setSiteDao(SiteDao siteDao) {
		this.siteDao = siteDao;
	}

	@Required
	public void setSiteGroupDao(SiteGroupDao siteGroupDao) {
		this.siteGroupDao = siteGroupDao;
	}

	@Override
	public int createSite(SiteDTO siteDTO) {
		Site site = SiteConverter.convert(siteDTO);
		siteDao.persist(site);
		loggingService.logEvent(LogType.SITE_CREATED, site.toString());
		return site.getId();
	}

	@Override
	public int createGroup(String name) throws ObjectExistsException {
		return createGroup(name, null);
	}

	@Override
	public int createGroup(String name, Set<Integer> siteIDs) throws ObjectExistsException {
		try {
			SiteGroup siteGroup = new SiteGroup(name);
			siteGroupDao.persist(siteGroup);
			
			loggingService.logEvent(LogType.SITE_GROUP_CREATED, siteGroup.toString());
			
			if (siteIDs != null && !siteIDs.isEmpty()) {
				List<Site> sites = siteDao.getAll(siteIDs, false);
				addSitesToGroupInternal(sites, siteGroup);
			}
			siteGroupDao.flush();
			return siteGroup.getId();
		} catch (ConstraintViolationException e) {
			throw new ObjectExistsException(e);
		}
	}
	
	private void addSitesToGroupInternal(List<Site> sites, SiteGroup siteGroup) {
		loggingService.logEvent(LogType.SITES_ADDED_TO_GROUP, siteGroup.toString() + " <- " + sites.toString());
		siteGroupDao.addSitesToGroup(sites, siteGroup);
	}

	@Override
	public void addSitesToGroup(Set<Integer> siteIDs, int groupId) throws ObjectExistsException {
		try {
			addSitesToGroupInternal(siteDao.getAll(siteIDs, false), siteGroupDao.get(groupId, false));
			siteGroupDao.flush();
		} catch (ConstraintViolationException e) {
			throw new ObjectExistsException(e);
		}
	}

	@Override
	public void addSitesToGroup(Set<Integer> siteIDs, String groupName) throws ObjectExistsException {
		try {
			List<Site> sites = siteDao.getAll(siteIDs, false);
			SiteGroup siteGroup = siteGroupDao.getByName(groupName);
			addSitesToGroupInternal(sites, siteGroup);
			siteGroupDao.flush();
		} catch (ConstraintViolationException e) {
			throw new ObjectExistsException(e);
		}
	}

	@Override
	@Transactional(readOnly = true)
	public Set<Integer> getSitesOfGroup(int groupId) {
		List<Integer> siteIDs = siteGroupDao.getSiteIdsOfGroup(groupId);
		return new HashSet<Integer>(siteIDs);
	}

	@Override
	@Transactional(readOnly = true)
	public Set<Integer> getSitesOfGroup(String groupName) {
		List<Integer> siteIDs = siteGroupDao.getSitesIdsOfGroup(groupName);
		return new HashSet<Integer>(siteIDs);
	}
}
